/**
 * @FILE:PlvTypeManager.java
 * @AUTHOR:chenqiu
 * @DATE:2016年5月31日 下午2:38:31
 **/
package com.smarttest.common.beans.protolcol.plv;

import java.util.Date;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smarttest.common.beans.protolcol.Index;
import com.smarttest.common.beans.protolcol.plv.PlvDefine.PlvType;
import com.smarttest.common.util.DateUtil;
import com.smarttest.common.util.protocol.ByteUtil;


/*******************************************
 * @COMPANY:北京汇通天下科技有限公司
 * @CLASS:PlvTypeManager
 * @DESCRIPTION:
 * @AUTHOR:chenqiu
 * @VERSION:v1.0
 * @DATE:2016年5月31日 下午2:38:31
 *******************************************/
public class PlvParser {
	private Logger log = LoggerFactory.getLogger(this.getClass());	
    public PlvConfig getPlvConfig(int plvConfigId){
    	PlvConfig plvConfig=PlvConfigStorage.getPlvConfigs().get(plvConfigId);
    	if(plvConfig==null){
    		log.error("Smart-EMS 没有找到PLV配置 plvid: " +Integer.toHexString(plvConfigId));            
    	}
    	return plvConfig;
    }
    private void compareType(PlvConfig plvConfig,int length){
    	if((plvConfig.getType()==PlvType.WORD&&length!=2)
    			||(plvConfig.getType()==PlvType.DWORD&&length!=4)){
    		log.warn("报文类型长度有误 PLV ID: {}",plvConfig.getId());
    	}
    }
    public void parse(Map<String, Object> row, byte[] bodyData, Index index, PlvConfig plvConfig,int length) {
    	try{
	       String result=null;
	       switch(plvConfig.getType()){       
	       case BCD:
	            result = ByteUtil.parseByte2Bcd(bodyData, index,length);
	            break;
	       case BCD_TIME:
	            Date date = ByteUtil.bcd2Date(bodyData, index);
	            result=DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
	            break;
	        case BOOL:
	            int parsebool = ByteUtil.parseByte2Int(bodyData, index);    
	            result=Integer.toString(parsebool);
	            break;
	        case BYTE:
	        	if(plvConfig.isArray()){
			    	 result=this.processArray(bodyData, index, plvConfig, length);
			     }else{
			        int parseByte = ByteUtil.parseByte2Int(bodyData, index);
			        result=  CalculateExpression.calcLong(parseByte, plvConfig);
			     }
		        break;
	        case WORD:
			    int size=length/2;
			    if(size==0||length%2!=0){
			    	log.warn("长度有误 plv id= {}",plvConfig.getId());
			    	index.add(length);
			    	break;
			    }
			     if(plvConfig.isArray()){
			    	 result=this.processArray(bodyData, index, plvConfig, size);
			     }else{
				     long parseDWord=ByteUtil.parseWord(bodyData, index);
				     compareType(plvConfig,length);
				     result=CalculateExpression.calcLong(parseDWord, plvConfig);  
			    	 
			     }
			    break;
	         case DWORD:
			     int sizeDword=length/4;
			     if(sizeDword==0||length%4!=0){
			    		log.warn("长度有误 plv id= {}",plvConfig.getId());
				    	index.add(length);
				    	break;
				 }
			     if(plvConfig.isArray()){
			    	 result=this.processArray(bodyData, index, plvConfig, sizeDword);
			     }else{
				     long parseDWord=ByteUtil.parseDWord(bodyData, index);
				     compareType(plvConfig,length);
				     result=CalculateExpression.calcLong(parseDWord, plvConfig);        					  
			     }
		 	     break;
		     default:
			   break;
	       }
	       saveRecord(row,plvConfig,result);   
    	}catch(Exception ex){
    		log.error("Smart-EMS： 处理PLV ID {} 时报错。",plvConfig.getId(),ex); 
    	}

    }
    private void saveRecord(Map<String, Object> row,PlvConfig plvConfig,String value){ 
    	String id=plvConfig.getId().substring(2).toUpperCase();
    	id="x"+id;//以x开始
    	row.put(id, value);
    }
    private String processArray(byte[] bodyData, Index index, PlvConfig plvConfig,int size){
    	try{
	    	int id=Integer.parseInt(plvConfig.getId().substring(2), 16);
	    	if(0x721B==id){
	    		String resDword=calcSpeedAndRotatingRelation(bodyData,index,plvConfig);
	    		return resDword;
	    	}
    	    String[] display= plvConfig.getDisplay();
    	    boolean flag=false;
    	    if(display!=null&&display.length>1){
    	    	flag=true;
    	    }
    	    StringBuilder sb= new StringBuilder();
    	    sb.append("{");
		    for(int i=0;i<size;i++){
			   long parseValue=parseData(bodyData,index,plvConfig);
			   String temp=CalculateExpression.calcLong(parseValue, plvConfig);
			   if(flag){
				   sb.append(display[i]).append(":").append(temp);
			   }else{
				   sb.append(temp);
			   }				   
			   if(i<size-1){
				   sb.append(",");
			   }
		    }
		    sb.append("}");
		    return(sb.toString());
	     }catch(Exception ex){
    		log.error("处理数组显示出错",ex);
    		return null;
    	}
    }
    /**
	 * 速度-转速 持续时间矩阵中转速维度(10档)
	 */
	private static final int ROTATING_DIMENSION = 10;
	
	/**
	 * 速度-转速 持续时间矩阵中速度维度(10档)
	 */
	private static final int SPEED_DIMENSION = 10;
	public String calcSpeedAndRotatingRelation(byte[] data, Index index,PlvConfig plvConfig){
		int idx = index.get();
		Index localIdx = new Index(idx);
		int length=0;
		if(plvConfig.getType()==PlvType.DWORD) {
			length=4;
		}else if(plvConfig.getType()==PlvType.BYTE){
			length=1;
		}else{
			length=2;
		}
		if(length==0){
			log.warn("calcSpeedAndRotatingRelation数据有误");
			return null;
		}
		StringBuilder speedAndRotating = new StringBuilder();
		speedAndRotating.append("{");
		for (int i = 0; i < ROTATING_DIMENSION; i++) {
			speedAndRotating.append(calcSpeed(i)).append(":{");
			for (int j = 0; j < SPEED_DIMENSION; j++) {
				localIdx.setIndex(idx + (i + j * 10) * length);
				long time =parseData(data,localIdx,plvConfig);
				speedAndRotating.append(calcRotatingSpeed(j)).append(":").append(time);
				if (j < SPEED_DIMENSION - 1) {
					speedAndRotating.append(",");
				} 
			}
			speedAndRotating.append("}");
			if (i < ROTATING_DIMENSION - 1) {
				speedAndRotating.append(",");
			}
		}
		speedAndRotating.append("}");
		index.setIndex(idx + ROTATING_DIMENSION * SPEED_DIMENSION * length);
		return speedAndRotating.toString();
	}
	
	private long parseData(byte[] bodyData, Index index,PlvConfig plvConfig){
		long parseValue=0;
		if(plvConfig.getType()==PlvType.WORD){
			   parseValue=ByteUtil.parseWord(bodyData, index);
		   }else if(plvConfig.getType()==PlvType.DWORD){
			   parseValue=ByteUtil.parseDWord(bodyData, index);
		   }else if(plvConfig.getType()==PlvType.BYTE){
			   parseValue=ByteUtil.parseByte2Int(bodyData, index);
		   }
		return parseValue;
	}
	
	private int calcSpeed(int count){
		return 30 + 10 * count;
	}
	private int calcRotatingSpeed(int count){
		return 600 + 200 * count;
	}

}
